﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Data;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Xml;
using AMS.Core.DataAccess;
using AMS.Core.Entities;
using AMS.Core.Importors;
using AMS.WorkBill.DataAccess;
using AMS.WorkBill.Entities;
using VitCode.BaseDataPageCreator;
using VitCode.BaseDataPageCreator.Setting;
using VitCode.Castle.DataAccess;
using VitCode.Castle.Entities;
using VitCode.Castle.Helper;

namespace AMS.Web.WorkBill
{
    public class WoCommandImportor:AbstractImportor
    {
        private const string OPERATE = "操作",NAME="Name",COMMAND_PRO="CommandPro",
            MAX_LENGHT = "MaxLenght", IS_NOT_REPEAT = "IsNotRepeat", GET_FROM_OBJ_PRO = "GetFromObjPro", INSERT_NOT_NULL = "InsertNotNull";
        private const string KEY_COL_NAME = "资产条码", CHECK_FORMAT_TYPE="CheckFormatType";
        /*
         * <Column Name="资产条码" CommandPro="AssetInfo" MaxLenght="50" IsNotRepeat="true" GetFromObjPro="AssetInfo.Barcode"></Column>
         */
        private WorkBillAccess m_Access;

        private NameObjectDictionary m_ChildObjectSets = new NameObjectDictionary();
        private NameObjectDictionary m_ChildObjectKeys = new NameObjectDictionary();
        private NameObjectDictionary m_ObjectSets = new NameObjectDictionary();
        private StringCollection m_keyInfos = new StringCollection();
        private StringCollection m_CanUserBarcode = new StringCollection();
        
        private NameValueCollection m_ProNameSet;
        private readonly ObjXmlReader m_XmlReader;
        private WoSaveHelper m_WoSaveHelper;
        private WoPageBuilder m_WoPageBuilder;

        AssetState m_AssetState_Used;
        AssetState m_AssetState_Idleness;

        private string GetProNodeAttrVal(string AttrName,XmlNode proNode)
        {
            return m_WoSaveHelper.CurrPageBuilder.m_LoadHelper.XmlReader.GetNodeAttributeValue(proNode, AttrName, true);
        }

        private string ObjectName
        {
            get { return "工单命令行"; }
        }

        public WorkBillInfo CurrWoInfo
        {
            get { return m_WoInfo; }
        }

        private XmlNodeList m_XmlPorNodes;
        private WorkBillInfo m_WoInfo;

        public WoCommandImportor(string path, string sheetName, XmlNodeList proNodes, WorkBillInfo woInfo, WoSaveHelper woSaveHelper)
        {
            m_AssetState_Idleness = DataAccess.GetIdlenessAssetState();
            m_AssetState_Used = DataAccess.GetUsedAssetState();
            m_XmlPorNodes = proNodes;
            m_WoInfo = woInfo;
            m_ErrorMessage = new ErrorResult();
            m_ErrorMessage.TableName = "出错信息";
            FilePath = path;
            SheetName = sheetName;
            m_IsTrans = true;
            m_ImportNum = DataAccess.GetImportNum();
            m_WoSaveHelper = woSaveHelper;
            m_WoPageBuilder = new WoPageBuilder(woSaveHelper.CurrPage, m_WoSaveHelper.XmlSettingString);
        }

        private WorkBillAccess DataAccess
        {
            get
            {
                if (m_Access == null)
                    m_Access = new WorkBillAccess();
                return m_Access;
            }
        }

        protected override string[] Titles
        {
            get
            {
                string[] reVal = new string[m_XmlPorNodes.Count + 1];
                for(int i=0;i<m_XmlPorNodes.Count;i++)
                {
                    string strColName = GetProNodeAttrVal(NAME, m_XmlPorNodes[i]);
                    reVal[i] = strColName;
                }
                reVal[m_XmlPorNodes.Count] = OPERATE;
                return reVal;
            }
        }

        

        protected override object DataRowToObject(DataRow row)
        {
            string strKeyVal = ReturnColumnValue(row,KEY_COL_NAME);
            bool isInsert = (ReturnColumnValue(row, OPERATE) == INSERT);

            WoCommand result;
            if (isInsert)
            {
                result = new WoCommand();
                result.WoCode = m_WoInfo.Code;
                result.Flag = WoCommand.STATE_SET;
                InsertCount++;
                isInsert = true;
            }
            else
            {
                result = (WoCommand) m_ObjectSets[strKeyVal];
                UpdateCount++;
            }

            foreach(XmlNode proNode in m_XmlPorNodes)
            {
                string strName = GetProNodeAttrVal(NAME, proNode);
                string strCommPro = GetProNodeAttrVal(COMMAND_PRO, proNode);
                string strGetFromObjPro = GetProNodeAttrVal(GET_FROM_OBJ_PRO, proNode);
                string strColValue = ReturnColumnValue(row, strName);
                if(strGetFromObjPro.Length == 0)
                {
                    if (IsNeedToUpdateInfo(isInsert, row, strName))
                    {
                        PropertyInfo pi = result.GetType().GetProperty(strCommPro);
                        if (pi != null)
                        {
                            if (pi.PropertyType == typeof(String)
                                || pi.PropertyType == typeof(Int16) || pi.PropertyType == typeof(Int32) ||
                                pi.PropertyType == typeof(Int64) || pi.PropertyType == typeof(Double))
                                pi.SetValue(result, Convert.ChangeType(strColValue,pi.PropertyType), null);
                        }
                    }
                }
                else
                {
                    if (IsNeedToUpdateInfo(isInsert, row, strName))
                    {
                        if (m_ChildObjectSets.Contains(strCommPro))
                        {
                            object objChildObjSet = m_ChildObjectSets[strCommPro];
                            NameObjectDictionary nd=null;
                            if(objChildObjSet != null && objChildObjSet is NameObjectDictionary)
                                nd = (NameObjectDictionary) objChildObjSet;
                            if (strGetFromObjPro.IndexOf(".") < 0)
                                continue;
                            string strClassName = strGetFromObjPro.Substring(0,strGetFromObjPro.IndexOf("."));
                            string strKeyProName = strGetFromObjPro.Substring(strGetFromObjPro.IndexOf(".")+1);
                            PropertyInfo pi = result.GetType().GetProperty(strCommPro);
                            if (pi != null && nd != null && nd.Contains(strColValue))
                                pi.SetValue(result, nd[strColValue], null);

                        }
                    }
                }
            }
            //如果命令行没有指定目标部门,而指定了目标用户,则以目标用记的所属部门为目标部门
            if (result.TargetUser != null && result.TargetUserGroup == null && result.TargetUser.UserGroup != null)
                result.TargetUserGroup = result.TargetUser.UserGroup;
            //如果命令行没有指定目标部门,而指定了目标地点,则以目标用记的所属部门为目标部门
            if (result.TargetSite != null && result.TargetUserGroup == null && result.TargetSite.Department != null)
                result.TargetUserGroup = result.TargetSite.Department;
            if (result.TargetState == null && result.TargetSite != null)
            {
                result.TargetState = result.TargetSite.TypeName.ToLower() == "warehouse" ? m_AssetState_Idleness : m_AssetState_Used;
            }

            return result;
        }

        protected override void SaveObjects(IList objects)
        {
            AssetState engrossAssetState = DataAccess.GetEngrossAssetState();
            if (IsTrans)
                DataAccess.BeginTransaction();
            try
            {
                foreach (WoCommand obj in objects)
                {
                    m_WoSaveHelper.SetInitCommandProSet(obj, m_WoInfo.GetType().Name,m_WoInfo.TypeName);
                    AssetInfo assetInfo = obj.AssetInfo;
                    assetInfo.State = engrossAssetState;
                    DataAccess.SaveOrUpdate(m_WoInfo);
                    DataAccess.SaveOrUpdate(assetInfo);
                    DataAccess.SaveOrUpdate(obj);
                }
                if (IsTrans)
                    DataAccess.Commit();
            }
            catch (Exception e)
            {
                if (m_IsTrans)
                    DataAccess.RollBack();
                throw e;
            }
            finally
            {
                if (m_IsTrans)
                    DataAccess.CloseSession();
            }
        }

        private StringCollection GetIsCanUseBarcode(BaseDataAccess acc)
        {
            StringCollection sc = new StringCollection();
            string strClassName = m_WoInfo.GetType().Name;
            string strTypeName = m_WoInfo.TypeName;
            string strSql = m_WoPageBuilder.GetSelectListSqlValue(strClassName, strTypeName);
            if (strSql.Length == 0)
                return sc;
            strSql = "Select " + KEY_COL_NAME + " from (" + strSql + ") x ";
            DataTable dt = new SqlHelper().GetDataTable(strSql,KEY_COL_NAME,m_keyInfos,acc);
            if(dt!=null && dt.Columns.Count>0 && dt.Rows.Count > 0)
            {
                foreach(DataRow r in dt.Rows)
                {
                    string colVal = r[KEY_COL_NAME].ToString();
                    if (!sc.Contains(colVal))
                        sc.Add(colVal);
                }
            }
            return sc;
        }

        protected override void GetDBRecordSet()
        {
            try
            {
                m_ObjectSets = DataAccess.GetObjectsByKeyValues(typeof (WoCommand).Name, "AssetInfo.Barcode", m_keyInfos,"o.Flag<>'"+WoCommand.STATE_EXEC+"'");
                m_CanUserBarcode = GetIsCanUseBarcode(DataAccess);
                foreach(XmlNode proNode in m_XmlPorNodes)
                {
                    string strCommandPro = GetProNodeAttrVal(COMMAND_PRO, proNode);
                    string strGetFromObjPro = GetProNodeAttrVal(GET_FROM_OBJ_PRO, proNode);
                    StringCollection sc = (StringCollection)m_ChildObjectKeys[strCommandPro];

                    if (strGetFromObjPro.IndexOf(".") < 0)
                        continue;
                    string strClassName = strGetFromObjPro.Substring(0,strGetFromObjPro.IndexOf("."));
                    string strKeyProName = strGetFromObjPro.Substring(strGetFromObjPro.IndexOf(".")+1);
                    string strTypeName = "";
                    int charIndex = strClassName.IndexOf("_");
                    if (charIndex > 0)
                    {
                        strTypeName = strClassName.Substring(charIndex + 1);
                        strClassName = strClassName.Substring(0, charIndex);
                    }
                    NameObjectDictionary nd = DataAccess.GetObjectsByKeyValues(strClassName,strTypeName,strKeyProName, strKeyProName, sc);
                    if(!m_ChildObjectSets.Contains(strCommandPro))
                    {
                        m_ChildObjectSets.Add(strCommandPro, nd);
                    }
                }
            }
            finally
            {
                DataAccess.CloseSession();
            }
        }

        protected override ExcelHelper CreateExcelHelper(string path, string sheetName)
        {
            var helper = new ExcelHelper(path, sheetName);
            helper.NotRepleateColumns.AddColumnByName(KEY_COL_NAME);
            helper.NotEmptyColumns.AddColumnByName(OPERATE);
            return helper;
        }

        private StringCollection GetProValues(XmlNodeList proNodeList, string AttrName)
        {
            StringCollection sc = new StringCollection();
            foreach(XmlNode proNode in proNodeList)
            {
                string strVal = GetProNodeAttrVal(AttrName, proNode);
                string strName = GetProNodeAttrVal(NAME, proNode);
                if (strVal.Length > 0)
                    sc.Add(strName);
            }
            return sc;
        }

        protected override void CreateDBSearchCondition(DataRow row, ErrorResult errorResult, int excelRowNumber)
        {
            string Message = "";
            string strObjKeyVal = ReturnColumnValue(row, KEY_COL_NAME);


            string operate = Convert.ToString(row[OPERATE]).Trim();

            bool isInsert = (operate == INSERT);

            //控制非空字段的导入与更新操作
            var insertNoEmptyTitles = GetProValues(m_XmlPorNodes, INSERT_NOT_NULL);
                

            CheckInsertNoEmptyColumn(row, insertNoEmptyTitles, isInsert, errorResult, excelRowNumber);

            //不允许清除内容的列
            var updateNoDeleteTitles = GetProValues(m_XmlPorNodes, INSERT_NOT_NULL);

            CheckUpdateNoDeleteField(row, updateNoDeleteTitles, isInsert, errorResult, excelRowNumber);

            if (!CheckFieldLength(row, KEY_COL_NAME, 1, 50, out Message))
                errorResult.SetMessage(excelRowNumber, Message);
            else if (!m_keyInfos.Contains(strObjKeyVal))
                m_keyInfos.Add(strObjKeyVal);

            PageRuleHelper prh = new PageRuleHelper("");

            foreach(XmlNode proNode in m_XmlPorNodes)
            {
                string strName = GetProNodeAttrVal(NAME, proNode);
                string strColVal = ReturnColumnValue(row, strName);
                string strMaxLen = GetProNodeAttrVal(MAX_LENGHT, proNode);
                string strCommandPro = GetProNodeAttrVal(COMMAND_PRO, proNode);
                string strCheckFormatType = GetProNodeAttrVal(CHECK_FORMAT_TYPE, proNode);
                int maxLen = Convert.ToInt32(strMaxLen);
                int minLen = 0;
                if (insertNoEmptyTitles.Contains(strName))
                    minLen = 1;
                string strGetFromObjPro = GetProNodeAttrVal(GET_FROM_OBJ_PRO, proNode);

                if(!CheckFieldLength(row,strName,minLen,maxLen,out Message))
                {
                    errorResult.SetMessage(excelRowNumber, Message);
                }
                else if (strCheckFormatType.Length>0)
                {
                    
                    //string strRegVal = prh.GetPageRuleRegByTypeName(strCheckFormatType);
                    //string strErrMsg = prh.GetPageRuleErrMsgByTypeName(strCheckFormatType);
                    //Regex reg = new Regex(strRegVal);
                    //if (!reg.IsMatch(strColVal))
                        //errorResult.SetMessage(excelRowNumber, strName+"[" + strColVal + "]" + strErrMsg);
                    
                }
                else
                {
                    if (!m_ChildObjectKeys.Contains(strCommandPro))
                        m_ChildObjectKeys.Add(strCommandPro, new StringCollection());
                    StringCollection ndKeyInfos = (StringCollection)m_ChildObjectKeys[strCommandPro];
                    if(!ndKeyInfos.Contains(strColVal))
                        ndKeyInfos.Add(strColVal);
                }
            }
        }

        protected override void CheckInDb(DataRow row, int excelRowNumber, ErrorResult errorResult)
        {
            bool isInsert = (ReturnColumnValue(row, OPERATE) == INSERT);
            string msg = "";
            string strObjKeyProVal = ReturnColumnValue(row, KEY_COL_NAME);

            
                if (isInsert)
                {
                    if (!m_CanUserBarcode.Contains(strObjKeyProVal))
                        errorResult.SetMessage(excelRowNumber,
                                               KEY_COL_NAME + "为: [ " + strObjKeyProVal + " ] 的" + ObjectName +
                                               "不是符合条件的待选" + ObjectName);
                    else
                    {
                        if (CheckChildObjectExists(m_ObjectSets, strObjKeyProVal, KEY_COL_NAME, out msg))
                            errorResult.SetMessage(excelRowNumber,
                                                   KEY_COL_NAME + "为: [ " + strObjKeyProVal + " ] 的" + ObjectName +
                                                   "已经存在不能导入");
                    }
                }
                else
                {
                    if (!CheckChildObjectExists(m_ObjectSets, strObjKeyProVal, KEY_COL_NAME, out msg))
                        errorResult.SetMessage(excelRowNumber,
                                               KEY_COL_NAME + "为: [ " + strObjKeyProVal + " ] 的" + ObjectName +
                                               "不存在不能更新");
                }
            

            foreach(XmlNode proNode in m_XmlPorNodes)
            {
                string strName = GetProNodeAttrVal(NAME, proNode);
                string strCommandPro = GetProNodeAttrVal(COMMAND_PRO, proNode);
                object objNd = m_ChildObjectSets[strCommandPro];
                if(objNd != null && objNd is NameObjectDictionary)
                {
                    NameObjectDictionary nd = (NameObjectDictionary)objNd;
                    if (!CheckChildObjectExists(nd, row, strName, out msg))
                        errorResult.SetMessage(excelRowNumber, msg);
                    else
                    {
                        if(m_WoInfo.TargetUserGroup==null)
                        {
                            continue;
                        }
                        string strColName = ReturnColumnValue(row, strName);
                        if(strCommandPro == "TargetUser" && nd.Contains(strColName))
                        {
                            object objColVal = nd[strColName];
                            if(objColVal!=null && objColVal is User)
                            {
                                User u = objColVal as User;
                                if (!u.UserGroup.Equals(m_WoInfo.TargetUserGroup))
                                    errorResult.SetMessage(excelRowNumber,
                                                           "用户[" + u.Name + "]不属于目标部门[" + m_WoInfo.TargetUserGroup.Name +
                                                           "]");
                            }
                        }
                    }
                }
            }

            
        }
    }
}
